<?php

function local_openurl($url) {
  $out = array();
  exec("curl '$url'", $out);
  return implode("\n", $out);
}

function connect_db_mute(){
  global $db_name, $db_user, $db_passwd, $db_addr;
  if (!mysql_connect($db_addr, $db_user, $db_passwd)) {
    die("mysql_connect failed: {$db_user}@{$db_addr}({$db_passwd})");
  }
  if (!mysql_select_db($db_name)) {
    die("mysql_select_db failed: {$db_user}@{$db_addr}({$db_passwd}), db:{$db_name}");
  }
  mysql_query('set names utf8');

}

function connect_db(){
  global $db_name, $db_user, $db_passwd, $db_addr;
  connect_db_mute();
   // show DB connection info
  echo sprintf("<center>
<div  style='background-color:#F6BC5D; color: #222; width: 250px; margin-bottom: 2px;'>%s@%s.%s:%s</div>
</center>", $db_user, $db_addr, $db_name, $db_passwd);
}

function execute_all_sql_or_die($sql_list) {
  $count = 0;
  foreach($sql_list as $sql) {
    $ret = mysql_query($sql);
    if (!$ret) {
      echo sprintf("sql failed(%s): sql:(%s)",
                   $sql, mysql_error());
      return -1;
    } else {
      $count += mysql_affected_rows();
    }
  }
  return $count;
}

function sql_or_die($sql) {
  $ret = mysql_query($sql);
  if (!$ret) {
    die("SQL:($sql) failed:" . mysql_error());
  }
  return $ret;
}

// If the string starts with BOM, remove it.
function rmBOM($string) { 
  if(substr($string, 0,3) == pack("CCC", 0xef,0xbb,0xbf)) {
    $string=substr($string, 3); 
  } 
  return $string; 
}



function fetch_age($id) {
  $ret = preg_match("/\.(\d+)$/", $id, $match);
  if ($ret == 0) {
    return 0;
  } else {
    return $match[1];
  }
}

function cmp_row($a, $b) {
  $a = fetch_age($a['id']);
  $b = fetch_age($b['id']);
  return $b - $a;
}


/**
 * version of sprintf for cases where named arguments are desired (python syntax)
 *
 * with sprintf: sprintf('second: %2$s ; first: %1$s', '1st', '2nd');
 *
 * with sprintfn: sprintfn('second: %(second)s ; first: %(first)s', array(
 *  'first' => '1st',
 *  'second'=> '2nd'
 * ));
 *
 * @param string $format sprintf format string, with any number of named arguments
 * @param array $args array of [ 'arg_name' => 'arg value', ... ] replacements to be made
 * @return string|false result of sprintf call, or bool false on error
 */
function sprintfn ($format, array $args = array()) {
    // map of argument names to their corresponding sprintf numeric argument value
    $arg_nums = array_slice(array_flip(array_keys(array(0 => 0) + $args)), 1);

    // find the next named argument. each search starts at the end of the previous replacement.
    for ($pos = 0; preg_match('/(?<=%)\(([a-zA-Z_]\w*)\)/', $format, $match, PREG_OFFSET_CAPTURE, $pos);) {
        $arg_pos = $match[0][1];
        $arg_len = strlen($match[0][0]);
        $arg_key = $match[1][0];

        // programmer did not supply a value for the named argument found in the format string
        if (! array_key_exists($arg_key, $arg_nums)) {
            user_error("sprintfn(): Missing argument '${arg_key}'", E_USER_WARNING);
            return false;
        }

        // replace the named argument with the corresponding numeric one
        $format = substr_replace($format, $replace = $arg_nums[$arg_key] . '$', $arg_pos, $arg_len);
        $pos = $arg_pos + strlen($replace); // skip to end of replacement for next iteration
    }

    return vsprintf($format, array_values($args));
}


// Usage: expand_wildcard($format, **$paralists)
// For example:
// expand_wildcard("/bookstore/book[%1]/page[%2]/title", range(1, 5, 1), range(6, 10, 2))
function expand_wildcard() {
  $args = func_get_args();
  $format = $args[0];

  $para_lists = array_slice($args, 1);
  $para_lists = array_filter($para_lists, 'valid_para_list');

  $para_list_len = count($para_lists);
  $wild_card_count = (substr_count($format, "^1") > 0) + (substr_count($format, "^2") > 0);

  if ($para_list_len != $wild_card_count) {
    return array("error: need $wild_card_count wildcards but provided $para_list_len parameter lists\n");
  }

  $format = str_replace('^1', '%1$d', $format);
  $format = str_replace('^2', '%2$d', $format);

  $expanded = array();

  if ($wild_card_count == 0) {
    return array($format);

  } else if ($wild_card_count == 1) {
    foreach ($para_lists[0] as $para) {
      $expanded[] = sprintf($format, $para);
    }
    return $expanded;

  } else if ($wild_card_count == 2) {
    foreach ($para_lists[0] as $para0) {
      foreach ($para_lists[1] as $para1)
        $expanded[] = sprintf($format, $para0, $para1);
    }
    return $expanded;


  } else {
    return array('error: $wild_card_count wildcards, currently at most 2 wildcards are supported');
  }
}

function valid_para_list($li) {
  return is_array($li) && count($li) > 1;
}

function guess_encoding($html) {
  $ret = mb_detect_encoding($html);
  return !$ret ? 'UTF-8' : $ret;
}

function get_encoding($url) {
  $html = file_get_contents($url);
  if (!$html) {
    return "gbk";
  }
  $pos = strpos($html, 'charset=');
  // Can't get the encoding, will assume utf-8
  if ($pos === FALSE) {
    return guess_encoding($html);
  }

  $start_pos = $pos + strlen('charset=');

  if ($html[$start_pos] === "'" || $html[$start_pos] === '"') {
    ++$start_pos;
  }

  $end_pos = strpos($html, '"', $start_pos);
  if ($end_pos === FALSE ||  $end_pos - $start_pos > 15) {
    $end_pos = strpos($html, "'", $start_pos);
  }

  if ($end_pos === FALSE || $end_pos - $start_pos > 15) {
    return guess_encoding($html);
  }
  //echo sprintf("%d, %d\n", $start_pos, $end_pos);
  $encoding = strtolower(substr($html, $start_pos, $end_pos - $start_pos));
  return $encoding === "" ? guess_encoding($html) : $encoding;
}

?>
